package com.platform.modules.wallet.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.platform.common.exception.BaseException;
import com.platform.common.web.service.impl.BaseServiceImpl;
import com.platform.modules.chat.domain.ChatUser;
import com.platform.modules.chat.service.ChatUserService;
import com.platform.modules.chat.vo.ChatVo01;
import com.platform.modules.wallet.dao.WalletTransferDao;
import com.platform.modules.wallet.domain.Wallet;
import com.platform.modules.wallet.domain.WalletAccount;
import com.platform.modules.wallet.domain.WalletTransfer;
import com.platform.modules.wallet.enums.AccountTypeEnum;
import com.platform.modules.wallet.enums.TransferInEnum;
import com.platform.modules.wallet.enums.TransferOutEnum;
import com.platform.modules.wallet.enums.TransferStatusEnum;
import com.platform.modules.wallet.service.WalletAccountService;
import com.platform.modules.wallet.service.WalletService;
import com.platform.modules.wallet.service.WalletTransferService;
import com.platform.modules.wallet.utils.TransferUtils;
import com.platform.modules.wallet.vo.AccountVo01;
import com.platform.modules.wallet.vo.TransferVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;

@Slf4j
@Service("walletTransferService")
public class WalletTransferServiceImpl extends BaseServiceImpl<WalletTransfer> implements WalletTransferService {

    @Resource
    private ChatUserService chatUserService;
    @Resource
    private WalletAccountService walletAccountService;
    @Resource
    private WalletService walletService;
    @Resource
    private WalletTransferDao walletTransferDao;

    @Autowired
    private TransferUtils transferUtils;

    @Autowired
    public void setBaseDao() {
        super.setBaseDao(walletTransferDao);
    }


    @Override
    public WalletTransfer transfer(ChatVo01 chatVo, Long userId) {

        Wallet wallet = walletService.getWallet(userId);
        // 当前用户
        ChatUser cu = chatUserService.getById(userId);
        transferUtils.verifySend(chatVo.getContent(), wallet, cu);

        JSONObject json = JSONUtil.parseObj(chatVo.getContent());
        int amount = new BigDecimal(json.getStr("amount")).multiply(BigDecimal.valueOf(100)).intValue();
        String queryId = json.getStr("queryId");

        TransferVo transferVo = new TransferVo();
        transferVo.setFromId(userId);
        transferVo.setToId(chatVo.getUserId());
        transferVo.setAmount(amount);
        transferVo.setQueryId(queryId);

        return createTransfer(transferVo);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void receive(String queryId, Long userId) {

        WalletTransfer transfer = getByQueryId(queryId);

        if (!ObjectUtil.equal(userId, transfer.getToId())) {
            throw new BaseException("收款人ID匹配错误");
        }

        this.successIn(transfer.getId());//完成收

        AccountVo01 accountVo = new AccountVo01();
        accountVo.setOtherId(transfer.getId());
        accountVo.setAmount(transfer.getAmount());
        accountVo.setType(AccountTypeEnum.TRANSFER_IN);
        accountVo.setUserId(userId);

        WalletAccount account = walletAccountService.createRecord(accountVo);
        walletAccountService.successRecord(account.getId());//完成账本记录
        walletService.add(accountVo.getAmount(), account.getUserId());//加余额 完成入
        successTransfer(transfer.getId());//完成出、收、入
    }

    @Override
    public WalletTransfer getByQueryId(String queryId) {
        WalletTransfer walletTransfer = new WalletTransfer()
                .selectOne(
                        new LambdaQueryWrapper<WalletTransfer>()
                                .eq(WalletTransfer::getQueryId, queryId));
        if (walletTransfer == null) {
            throw new BaseException("对象不存在");
        }
        return walletTransfer;

    }

    @Override
    public List<WalletTransfer> getRefun() {

        DateTime date = DateUtil.date();
        return new WalletTransfer().selectList(new LambdaQueryWrapper<WalletTransfer>()
                .eq(WalletTransfer::getStatus, TransferStatusEnum.INIT)
                .eq(WalletTransfer::getOutStatus, TransferOutEnum.SUCCESS)
                .eq(WalletTransfer::getInStatus, TransferInEnum.INIT)
                .le(WalletTransfer::getRefundableTime, date));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void refund(Long id) {
        WalletTransfer transfer = findById(id);
        if (!TransferStatusEnum.INIT.equals(transfer.getStatus())) {
            throw new BaseException("订单转态已完成出、收、入");
        }
        if (!TransferOutEnum.SUCCESS.equals(transfer.getOutStatus())) {
            throw new BaseException("转账转出未完成");
        }
        if (!TransferInEnum.INIT.equals(transfer.getInStatus())) {
            throw new BaseException("转账接收已完成");
        }

        DateTime date = DateUtil.date();
        transfer.setStatus(TransferStatusEnum.REFUND);
        transfer.setRefundTime(date);
        transfer.setUpdateTime(date);
        updateById(transfer);


        AccountVo01 accountVo = new AccountVo01();
        accountVo.setOtherId(transfer.getId());
        accountVo.setAmount(transfer.getAmount());
        accountVo.setType(AccountTypeEnum.REFUND);
        accountVo.setUserId(transfer.getFromId());

        WalletAccount account = walletAccountService.createRecord(accountVo);
        walletAccountService.successRecord(account.getId());//完成账本记录
        walletService.add(accountVo.getAmount(), account.getUserId());//加余额 完成入
    }

    @Transactional(rollbackFor = Exception.class)
    public WalletTransfer createTransfer(TransferVo vo) {

        WalletTransfer bean = getBean();
        bean.setQueryId(vo.getQueryId());
        bean.setAmount(vo.getAmount());
        bean.setFromId(vo.getFromId());
        bean.setToId(vo.getToId());
        add(bean);

        AccountVo01 accountVo = new AccountVo01();
        accountVo.setOtherId(bean.getId());
        accountVo.setAmount(vo.getAmount());
        accountVo.setType(AccountTypeEnum.TRANSFER_OUT);
        accountVo.setUserId(bean.getFromId());

        WalletAccount account = walletAccountService.createRecord(accountVo, WalletAccountService.NEGATIVE);

        walletAccountService.successRecord(account.getId());//完成账本记录
        synchronized(this){
            walletService.subtract(accountVo.getAmount(), account.getUserId());//减掉余额 完成出账
        }
        successOut(bean.getId());//完成出账转态
        return bean;
    }

    /**
     * 完成转出状态
     *
     * @param id
     */
    private void successOut(Long id) {
        WalletTransfer transfer = findById(id);
        transfer.setOutStatus(TransferOutEnum.SUCCESS);
        transfer.setUpdateTime(DateUtil.date());
        updateById(transfer);
    }

    /**
     * 完成接收状态
     *
     * @param id
     */
    private void successIn(Long id) {

        WalletTransfer transfer = findById(id);

        if (ObjectUtil.equal(TransferInEnum.SUCCESS, transfer.getInStatus())) {
            throw new BaseException("转账订单状态异常(已经完成了):inStatus=" + transfer.getInStatus());
        }
        if (!ObjectUtil.equal(TransferStatusEnum.INIT, transfer.getStatus())) {
            throw new BaseException("转账订单状态异常:status=" + transfer.getStatus());
        }
        if (!ObjectUtil.equal(TransferOutEnum.SUCCESS, transfer.getOutStatus())) {
            throw new BaseException("转账订单转出状态异常:outStatus=" + transfer.getOutStatus());
        }
        transfer.setInStatus(TransferInEnum.SUCCESS);
        transfer.setReceiveTime(DateUtil.date());
        transfer.setUpdateTime(DateUtil.date());
        updateById(transfer);
    }

    private void successTransfer(Long id) {
        WalletTransfer transfer = findById(id);
        transfer.setStatus(TransferStatusEnum.SUCCESS);
        transfer.setSuccessTime(DateUtil.date());
        updateById(transfer);
    }

    private WalletTransfer getBean() {
        WalletTransfer transfer = new WalletTransfer();
        transfer.setOutStatus(TransferOutEnum.INIT);
        transfer.setInStatus(TransferInEnum.INIT);
        transfer.setStatus(TransferStatusEnum.INIT);
        DateTime date = DateUtil.date();
        transfer.setCreateTime(date);
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.add(calendar.DATE, 1);//把日期往后增加一天.整数往后推,负数往前移动
        date = DateUtil.date(calendar.getTime()); //这个时间就是日期往后推一天的结果
        transfer.setRefundableTime(date);
        return transfer;
    }
}
